1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 package com.sun.java.util.jar.pack;
27
28 import com.sun.java.util.jar.pack.ConstantPool.ClassEntry;
29 import com.sun.java.util.jar.pack.ConstantPool.DescriptorEntry;
30 import com.sun.java.util.jar.pack.ConstantPool.Entry;
31 import com.sun.java.util.jar.pack.ConstantPool.Index;
32 import com.sun.java.util.jar.pack.ConstantPool.MemberEntry;
33 import com.sun.java.util.jar.pack.ConstantPool.SignatureEntry;
34 import com.sun.java.util.jar.pack.ConstantPool.Utf8Entry;
35 import com.sun.java.util.jar.pack.Package.Class;
36 import com.sun.java.util.jar.pack.Package.File;
37 import com.sun.java.util.jar.pack.Package.InnerClass;
38 import java.io.ByteArrayOutputStream;
39 import java.io.EOFException;
40 import java.io.PrintStream;
41 import java.io.FilterInputStream;
42 import java.io.BufferedInputStream;
43 import java.io.InputStream;
44 import java.io.IOException;
45 import java.util.ArrayList;
46 import java.util.Map;
47 import java.util.Arrays;
48 import java.util.Collection;
49 import java.util.Comparator;
50 import java.util.HashSet;
51 import java.util.HashMap;
52 import java.util.Iterator;
53 import java.util.List;
54 import java.util.ListIterator;
55 import java.util.Set;
56 import static com.sun.java.util.jar.pack.Constants.*;
57
58
59
60
61
62
63
64 class PackageReader extends BandStructure {
65 Package pkg;
66 byte[] bytes;
67 LimitedBuffer in;
68
69 PackageReader(Package pkg, InputStream in) throws IOException {
70 this.pkg = pkg;
71 this.in = new LimitedBuffer(in);
72 }
73
74
75
76
77
78
79
80 static
81 class LimitedBuffer extends BufferedInputStream {
82 long served;
83 int servedPos;
84 long limit;
85 long buffered;
86 public boolean atLimit() {
87 boolean z = (getBytesServed() == limit);
88 assert(!z || limit == buffered);
89 return z;
90 }
91 public long getBytesServed() {
92 return served + (pos - servedPos);
93 }
94 public void setReadLimit(long newLimit) {
95 if (newLimit == -1)
96 limit = -1;
97 else
98 limit = getBytesServed() + newLimit;
99 }
100 public long getReadLimit() {
101 if (limit == -1)
102 return limit;
103 else
104 return limit - getBytesServed();
105 }
106 public int read() throws IOException {
107 if (pos < count) {
108
109 return buf[pos++] & 0xFF;
110 }
111 served += (pos - servedPos);
112 int ch = super.read();
113 servedPos = pos;
114 if (ch >= 0) served += 1;
115 assert(served <= limit || limit == -1);
116 return ch;
117 }
118 public int read(byte b[], int off, int len) throws IOException {
119 served += (pos - servedPos);
120 int nr = super.read(b, off, len);
121 servedPos = pos;
122 if (nr >= 0) served += nr;
123 assert(served <= limit || limit == -1);
124 return nr;
125 }
126 public long skip(long n) throws IOException {
127 throw new RuntimeException("no skipping");
128 }
129 LimitedBuffer(InputStream originalIn) {
130 super(null, 1<<14);
131 servedPos = pos;
132 super.in = new FilterInputStream(originalIn) {
133 public int read() throws IOException {
134 if (buffered == limit)
135 return -1;
136 ++buffered;
137 return super.read();
138 }
139 public int read(byte b[], int off, int len) throws IOException {
140 if (buffered == limit)
141 return -1;
142 if (limit != -1) {
143 long remaining = limit - buffered;
144 if (len > remaining)
145 len = (int)remaining;
146 }
147 int nr = super.read(b, off, len);
148 if (nr >= 0) buffered += nr;
149 return nr;
150 }
151 };
152 }
153 }
154
155 void read() throws IOException {
156 boolean ok = false;
157 try {
158
159
160
161
162
163
164
165
166
167 readFileHeader();
168 readBandHeaders();
169 readConstantPool();
170 readAttrDefs();
171 readInnerClasses();
172 Class[] classes = readClasses();
173 readByteCodes();
174 readFiles();
175 assert(archiveSize1 == 0 || in.atLimit());
176 assert(archiveSize1 == 0 ||
177 in.getBytesServed() == archiveSize0+archiveSize1);
178 all_bands.doneDisbursing();
179
180
181 for (int i = 0; i < classes.length; i++) {
182 reconstructClass(classes[i]);
183 }
184
185 ok = true;
186 } catch (Exception ee) {
187 Utils.log.warning("Error on input: "+ee, ee);
188 if (verbose > 0)
189 Utils.log.info("Stream offsets:"+
190 " served="+in.getBytesServed()+
191 " buffered="+in.buffered+
192 " limit="+in.limit);
193
194 if (ee instanceof IOException) throw (IOException)ee;
195 if (ee instanceof RuntimeException) throw (RuntimeException)ee;
196 throw new Error("error unpacking", ee);
197 }
198 }
199
200
201 int[] tagCount = new int[CONSTANT_Limit];
202 int numFiles;
203 int numAttrDefs;
204 int numInnerClasses;
205 int numClasses;
206
207 void readFileHeader() throws IOException {
208
209
210 readArchiveMagic();
211 readArchiveHeader();
212 }
213
214
215
216 private int getMagicInt32() throws IOException {
217 int res = 0;
218 for (int i = 0; i < 4; i++) {
219 res <<= 8;
220 res |= (archive_magic.getByte() & 0xFF);
221 }
222 return res;
223 }
224
225 final static int MAGIC_BYTES = 4;
226
227 void readArchiveMagic() throws IOException {
228
229
230 in.setReadLimit(MAGIC_BYTES + AH_LENGTH_MIN);
231
232
233
234 archive_magic.expectLength(MAGIC_BYTES);
235 archive_magic.readFrom(in);
236
237
238 pkg.magic = getMagicInt32();
239 archive_magic.doneDisbursing();
240 }
241
242 void readArchiveHeader() throws IOException {
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269 assert(AH_LENGTH == 8+(ConstantPool.TAGS_IN_ORDER.length)+6);
270 archive_header_0.expectLength(AH_LENGTH_0);
271 archive_header_0.readFrom(in);
272
273 pkg.package_minver = archive_header_0.getInt();
274 pkg.package_majver = archive_header_0.getInt();
275 pkg.checkVersion();
276 this.initPackageMajver(pkg.package_majver);
277
278 archiveOptions = archive_header_0.getInt();
279 archive_header_0.doneDisbursing();
280
281
282 boolean haveSpecial = testBit(archiveOptions, AO_HAVE_SPECIAL_FORMATS);
283 boolean haveFiles = testBit(archiveOptions, AO_HAVE_FILE_HEADERS);
284 boolean haveNumbers = testBit(archiveOptions, AO_HAVE_CP_NUMBERS);
285 initAttrIndexLimit();
286
287
288 archive_header_S.expectLength(haveFiles? AH_LENGTH_S: 0);
289 archive_header_S.readFrom(in);
290 if (haveFiles) {
291 long sizeHi = archive_header_S.getInt();
292 long sizeLo = archive_header_S.getInt();
293 archiveSize1 = (sizeHi << 32) + ((sizeLo << 32) >>> 32);
294
295 in.setReadLimit(archiveSize1);
296 } else {
297 archiveSize1 = 0;
298 in.setReadLimit(-1);
299 }
300 archive_header_S.doneDisbursing();
301 archiveSize0 = in.getBytesServed();
302
303 int remainingHeaders = AH_LENGTH - AH_LENGTH_0 - AH_LENGTH_S;
304 if (!haveFiles) remainingHeaders -= AH_FILE_HEADER_LEN-AH_LENGTH_S;
305 if (!haveSpecial) remainingHeaders -= AH_SPECIAL_FORMAT_LEN;
306 if (!haveNumbers) remainingHeaders -= AH_CP_NUMBER_LEN;
307 assert(remainingHeaders >= AH_LENGTH_MIN - AH_LENGTH_0);
308 archive_header_1.expectLength(remainingHeaders);
309 archive_header_1.readFrom(in);
310
311 if (haveFiles) {
312 archiveNextCount = archive_header_1.getInt();
313 pkg.default_modtime = archive_header_1.getInt();
314 numFiles = archive_header_1.getInt();
315 } else {
316 archiveNextCount = 0;
317 numFiles = 0;
318 }
319
320 if (haveSpecial) {
321 band_headers.expectLength(archive_header_1.getInt());
322 numAttrDefs = archive_header_1.getInt();
323 } else {
324 band_headers.expectLength(0);
325 numAttrDefs = 0;
326 }
327
328 readConstantPoolCounts(haveNumbers);
329
330 numInnerClasses = archive_header_1.getInt();
331
332 pkg.default_class_minver = (short) archive_header_1.getInt();
333 pkg.default_class_majver = (short) archive_header_1.getInt();
334 numClasses = archive_header_1.getInt();
335
336 archive_header_1.doneDisbursing();
337
338
339 if (testBit(archiveOptions, AO_DEFLATE_HINT)) {
340 pkg.default_options |= FO_DEFLATE_HINT;
341 }
342 }
343
344 void readBandHeaders() throws IOException {
345 band_headers.readFrom(in);
346 bandHeaderBytePos = 1;
347 bandHeaderBytes = new byte[bandHeaderBytePos + band_headers.length()];
348 for (int i = bandHeaderBytePos; i < bandHeaderBytes.length; i++) {
349 bandHeaderBytes[i] = (byte) band_headers.getByte();
350 }
351 band_headers.doneDisbursing();
352 }
353
354 void readConstantPoolCounts(boolean haveNumbers) throws IOException {
355
356 for (int k = 0; k < ConstantPool.TAGS_IN_ORDER.length; k++) {
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374 byte tag = ConstantPool.TAGS_IN_ORDER[k];
375 if (!haveNumbers) {
376
377 switch (tag) {
378 case CONSTANT_Integer:
379 case CONSTANT_Float:
380 case CONSTANT_Long:
381 case CONSTANT_Double:
382 continue;
383 }
384 }
385 tagCount[tag] = archive_header_1.getInt();
386 }
387 }
388
389 protected Index getCPIndex(byte tag) {
390 return pkg.cp.getIndexByTag(tag);
391 }
392 Index initCPIndex(byte tag, Entry[] cpMap) {
393 if (verbose > 3) {
394 for (int i = 0; i < cpMap.length; i++) {
395 Utils.log.fine("cp.add "+cpMap[i]);
396 }
397 }
398 Index index = ConstantPool.makeIndex(ConstantPool.tagName(tag), cpMap);
399 if (verbose > 1) Utils.log.fine("Read "+index);
400 pkg.cp.initIndexByTag(tag, index);
401 return index;
402 }
403
404 void readConstantPool() throws IOException {
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419 if (verbose > 0) Utils.log.info("Reading CP");
420
421 for (int k = 0; k < ConstantPool.TAGS_IN_ORDER.length; k++) {
422 byte tag = ConstantPool.TAGS_IN_ORDER[k];
423 int len = tagCount[tag];
424
425 Entry[] cpMap = new Entry[len];
426 if (verbose > 0)
427 Utils.log.info("Reading "+cpMap.length+" "+ConstantPool.tagName(tag)+" entries...");
428
429 switch (tag) {
430 case CONSTANT_Utf8:
431 readUtf8Bands(cpMap);
432 break;
433 case CONSTANT_Integer:
434 cp_Int.expectLength(cpMap.length);
435 cp_Int.readFrom(in);
436 for (int i = 0; i < cpMap.length; i++) {
437 int x = cp_Int.getInt();
438 cpMap[i] = ConstantPool.getLiteralEntry(x);
439 }
440 cp_Int.doneDisbursing();
441 break;
442 case CONSTANT_Float:
443 cp_Float.expectLength(cpMap.length);
444 cp_Float.readFrom(in);
445 for (int i = 0; i < cpMap.length; i++) {
446 int x = cp_Float.getInt();
447 float fx = Float.intBitsToFloat(x);
448 cpMap[i] = ConstantPool.getLiteralEntry(fx);
449 }
450 cp_Float.doneDisbursing();
451 break;
452 case CONSTANT_Long:
453
454
455
456 cp_Long_hi.expectLength(cpMap.length);
457 cp_Long_hi.readFrom(in);
458 cp_Long_lo.expectLength(cpMap.length);
459 cp_Long_lo.readFrom(in);
460 for (int i = 0; i < cpMap.length; i++) {
461 long hi = cp_Long_hi.getInt();
462 long lo = cp_Long_lo.getInt();
463 long x = (hi << 32) + ((lo << 32) >>> 32);
464 cpMap[i] = ConstantPool.getLiteralEntry(x);
465 }
466 cp_Long_hi.doneDisbursing();
467 cp_Long_lo.doneDisbursing();
468 break;
469 case CONSTANT_Double:
470
471
472
473 cp_Double_hi.expectLength(cpMap.length);
474 cp_Double_hi.readFrom(in);
475 cp_Double_lo.expectLength(cpMap.length);
476 cp_Double_lo.readFrom(in);
477 for (int i = 0; i < cpMap.length; i++) {
478 long hi = cp_Double_hi.getInt();
479 long lo = cp_Double_lo.getInt();
480 long x = (hi << 32) + ((lo << 32) >>> 32);
481 double dx = Double.longBitsToDouble(x);
482 cpMap[i] = ConstantPool.getLiteralEntry(dx);
483 }
484 cp_Double_hi.doneDisbursing();
485 cp_Double_lo.doneDisbursing();
486 break;
487 case CONSTANT_String:
488 cp_String.expectLength(cpMap.length);
489 cp_String.readFrom(in);
490 cp_String.setIndex(getCPIndex(CONSTANT_Utf8));
491 for (int i = 0; i < cpMap.length; i++) {
492 cpMap[i] = ConstantPool.getLiteralEntry(cp_String.getRef().stringValue());
493 }
494 cp_String.doneDisbursing();
495 break;
496 case CONSTANT_Class:
497 cp_Class.expectLength(cpMap.length);
498 cp_Class.readFrom(in);
499 cp_Class.setIndex(getCPIndex(CONSTANT_Utf8));
500 for (int i = 0; i < cpMap.length; i++) {
501 cpMap[i] = ConstantPool.getClassEntry(cp_Class.getRef().stringValue());
502 }
503 cp_Class.doneDisbursing();
504 break;
505 case CONSTANT_Signature:
506 readSignatureBands(cpMap);
507 break;
508 case CONSTANT_NameandType:
509
510
511
512 cp_Descr_name.expectLength(cpMap.length);
513 cp_Descr_name.readFrom(in);
514 cp_Descr_name.setIndex(getCPIndex(CONSTANT_Utf8));
515 cp_Descr_type.expectLength(cpMap.length);
516 cp_Descr_type.readFrom(in);
517 cp_Descr_type.setIndex(getCPIndex(CONSTANT_Signature));
518 for (int i = 0; i < cpMap.length; i++) {
519 Entry ref = cp_Descr_name.getRef();
520 Entry ref2 = cp_Descr_type.getRef();
521 cpMap[i] = ConstantPool.getDescriptorEntry((Utf8Entry)ref,
522 (SignatureEntry)ref2);
523 }
524 cp_Descr_name.doneDisbursing();
525 cp_Descr_type.doneDisbursing();
526 break;
527 case CONSTANT_Fieldref:
528 readMemberRefs(tag, cpMap, cp_Field_class, cp_Field_desc);
529 break;
530 case CONSTANT_Methodref:
531 readMemberRefs(tag, cpMap, cp_Method_class, cp_Method_desc);
532 break;
533 case CONSTANT_InterfaceMethodref:
534 readMemberRefs(tag, cpMap, cp_Imethod_class, cp_Imethod_desc);
535 break;
536 default:
537 assert(false);
538 }
539
540 Index index = initCPIndex(tag, cpMap);
541
542 if (optDumpBands) {
543 try (PrintStream ps = new PrintStream(getDumpStream(index, ".idx"))) {
544 printArrayTo(ps, index.cpMap, 0, index.cpMap.length);
545 }
546 }
547 }
548
549 cp_bands.doneDisbursing();
550
551 setBandIndexes();
552 }
553
554 void readUtf8Bands(Entry[] cpMap) throws IOException {
555
556
557
558
559
560
561
562 int len = cpMap.length;
563 if (len == 0)
564 return;
565
566
567 final int SUFFIX_SKIP_1 = 1;
568 final int PREFIX_SKIP_2 = 2;
569
570
571 cp_Utf8_prefix.expectLength(Math.max(0, len - PREFIX_SKIP_2));
572 cp_Utf8_prefix.readFrom(in);
573
574
575 cp_Utf8_suffix.expectLength(Math.max(0, len - SUFFIX_SKIP_1));
576 cp_Utf8_suffix.readFrom(in);
577
578 char[][] suffixChars = new char[len][];
579 int bigSuffixCount = 0;
580
581
582 cp_Utf8_chars.expectLength(cp_Utf8_suffix.getIntTotal());
583 cp_Utf8_chars.readFrom(in);
584 for (int i = 0; i < len; i++) {
585 int suffix = (i < SUFFIX_SKIP_1)? 0: cp_Utf8_suffix.getInt();
586 if (suffix == 0 && i >= SUFFIX_SKIP_1) {
587
588 bigSuffixCount += 1;
589 continue;
590 }
591 suffixChars[i] = new char[suffix];
592 for (int j = 0; j < suffix; j++) {
593 int ch = cp_Utf8_chars.getInt();
594 assert(ch == (char)ch);
595 suffixChars[i][j] = (char)ch;
596 }
597 }
598 cp_Utf8_chars.doneDisbursing();
599
600
601 int maxChars = 0;
602 cp_Utf8_big_suffix.expectLength(bigSuffixCount);
603 cp_Utf8_big_suffix.readFrom(in);
604 cp_Utf8_suffix.resetForSecondPass();
605 for (int i = 0; i < len; i++) {
606 int suffix = (i < SUFFIX_SKIP_1)? 0: cp_Utf8_suffix.getInt();
607 int prefix = (i < PREFIX_SKIP_2)? 0: cp_Utf8_prefix.getInt();
608 if (suffix == 0 && i >= SUFFIX_SKIP_1) {
609 assert(suffixChars[i] == null);
610 suffix = cp_Utf8_big_suffix.getInt();
611 } else {
612 assert(suffixChars[i] != null);
613 }
614 if (maxChars < prefix + suffix)
615 maxChars = prefix + suffix;
616 }
617 char[] buf = new char[maxChars];
618
619
620 cp_Utf8_suffix.resetForSecondPass();
621 cp_Utf8_big_suffix.resetForSecondPass();
622 for (int i = 0; i < len; i++) {
623 if (i < SUFFIX_SKIP_1) continue;
624 int suffix = cp_Utf8_suffix.getInt();
625 if (suffix != 0) continue;
626 suffix = cp_Utf8_big_suffix.getInt();
627 suffixChars[i] = new char[suffix];
628 if (suffix == 0) {
629
630 continue;
631 }
632 IntBand packed = cp_Utf8_big_chars.newIntBand("(Utf8_big_"+i+")");
633 packed.expectLength(suffix);
634 packed.readFrom(in);
635 for (int j = 0; j < suffix; j++) {
636 int ch = packed.getInt();
637 assert(ch == (char)ch);
638 suffixChars[i][j] = (char)ch;
639 }
640 packed.doneDisbursing();
641 }
642 cp_Utf8_big_chars.doneDisbursing();
643
644
645 cp_Utf8_prefix.resetForSecondPass();
646 cp_Utf8_suffix.resetForSecondPass();
647 cp_Utf8_big_suffix.resetForSecondPass();
648 for (int i = 0; i < len; i++) {
649 int prefix = (i < PREFIX_SKIP_2)? 0: cp_Utf8_prefix.getInt();
650 int suffix = (i < SUFFIX_SKIP_1)? 0: cp_Utf8_suffix.getInt();
651 if (suffix == 0 && i >= SUFFIX_SKIP_1)
652 suffix = cp_Utf8_big_suffix.getInt();
653
654
655 System.arraycopy(suffixChars[i], 0, buf, prefix, suffix);
656
657 cpMap[i] = ConstantPool.getUtf8Entry(new String(buf, 0, prefix+suffix));
658 }
659
660 cp_Utf8_prefix.doneDisbursing();
661 cp_Utf8_suffix.doneDisbursing();
662 cp_Utf8_big_suffix.doneDisbursing();
663 }
664
665 Map<Utf8Entry, SignatureEntry> utf8Signatures;
666
667 void readSignatureBands(Entry[] cpMap) throws IOException {
668
669
670
671 cp_Signature_form.expectLength(cpMap.length);
672 cp_Signature_form.readFrom(in);
673 cp_Signature_form.setIndex(getCPIndex(CONSTANT_Utf8));
674 int[] numSigClasses = new int[cpMap.length];
675 for (int i = 0; i < cpMap.length; i++) {
676 Utf8Entry formRef = (Utf8Entry) cp_Signature_form.getRef();
677 numSigClasses[i] = ConstantPool.countClassParts(formRef);
678 }
679 cp_Signature_form.resetForSecondPass();
680 cp_Signature_classes.expectLength(getIntTotal(numSigClasses));
681 cp_Signature_classes.readFrom(in);
682 cp_Signature_classes.setIndex(getCPIndex(CONSTANT_Class));
683 utf8Signatures = new HashMap<>();
684 for (int i = 0; i < cpMap.length; i++) {
685 Utf8Entry formRef = (Utf8Entry) cp_Signature_form.getRef();
686 ClassEntry[] classRefs = new ClassEntry[numSigClasses[i]];
687 for (int j = 0; j < classRefs.length; j++) {
688 classRefs[j] = (ClassEntry) cp_Signature_classes.getRef();
689 }
690 SignatureEntry se = ConstantPool.getSignatureEntry(formRef, classRefs);
691 cpMap[i] = se;
692 utf8Signatures.put(se.asUtf8Entry(), se);
693 }
694 cp_Signature_form.doneDisbursing();
695 cp_Signature_classes.doneDisbursing();
696 }
697
698 void readMemberRefs(byte tag, Entry[] cpMap, CPRefBand cp_class, CPRefBand cp_desc) throws IOException {
699
700
701
702
703
704
705
706
707
708 cp_class.expectLength(cpMap.length);
709 cp_class.readFrom(in);
710 cp_class.setIndex(getCPIndex(CONSTANT_Class));
711 cp_desc.expectLength(cpMap.length);
712 cp_desc.readFrom(in);
713 cp_desc.setIndex(getCPIndex(CONSTANT_NameandType));
714 for (int i = 0; i < cpMap.length; i++) {
715 ClassEntry mclass = (ClassEntry ) cp_class.getRef();
716 DescriptorEntry mdescr = (DescriptorEntry) cp_desc.getRef();
717 cpMap[i] = ConstantPool.getMemberEntry(tag, mclass, mdescr);
718 }
719 cp_class.doneDisbursing();
720 cp_desc.doneDisbursing();
721 }
722
723 void readFiles() throws IOException {
724
725
726
727
728
729
730
731 if (verbose > 0)
732 Utils.log.info(" ...building "+numFiles+" files...");
733 file_name.expectLength(numFiles);
734 file_size_lo.expectLength(numFiles);
735 int options = archiveOptions;
736 boolean haveSizeHi = testBit(options, AO_HAVE_FILE_SIZE_HI);
737 boolean haveModtime = testBit(options, AO_HAVE_FILE_MODTIME);
738 boolean haveOptions = testBit(options, AO_HAVE_FILE_OPTIONS);
739 if (haveSizeHi)
740 file_size_hi.expectLength(numFiles);
741 if (haveModtime)
742 file_modtime.expectLength(numFiles);
743 if (haveOptions)
744 file_options.expectLength(numFiles);
745
746 file_name.readFrom(in);
747 file_size_hi.readFrom(in);
748 file_size_lo.readFrom(in);
749 file_modtime.readFrom(in);
750 file_options.readFrom(in);
751 file_bits.setInputStreamFrom(in);
752
753 Iterator nextClass = pkg.getClasses().iterator();
754
755
756 long totalFileLength = 0;
757 long[] fileLengths = new long[numFiles];
758 for (int i = 0; i < numFiles; i++) {
759 long size = ((long)file_size_lo.getInt() << 32) >>> 32;
760 if (haveSizeHi)
761 size += (long)file_size_hi.getInt() << 32;
762 fileLengths[i] = size;
763 totalFileLength += size;
764 }
765 assert(in.getReadLimit() == -1 || in.getReadLimit() == totalFileLength);
766
767 byte[] buf = new byte[1<<16];
768 for (int i = 0; i < numFiles; i++) {
769
770 Utf8Entry name = (Utf8Entry) file_name.getRef();
771 long size = fileLengths[i];
772 File file = pkg.new File(name);
773 file.modtime = pkg.default_modtime;
774 file.options = pkg.default_options;
775 if (haveModtime)
776 file.modtime += file_modtime.getInt();
777 if (haveOptions)
778 file.options |= file_options.getInt();
779 if (verbose > 1)
780 Utils.log.fine("Reading "+size+" bytes of "+name.stringValue());
781 long toRead = size;
782 while (toRead > 0) {
783 int nr = buf.length;
784 if (nr > toRead) nr = (int) toRead;
785 nr = file_bits.getInputStream().read(buf, 0, nr);
786 if (nr < 0) throw new EOFException();
787 file.addBytes(buf, 0, nr);
788 toRead -= nr;
789 }
790 pkg.addFile(file);
791 if (file.isClassStub()) {
792 assert(file.getFileLength() == 0);
793 Class cls = (Class) nextClass.next();
794 cls.initFile(file);
795 }
796 }
797
798
799 while (nextClass.hasNext()) {
800 Class cls = (Class) nextClass.next();
801 cls.initFile(null);
802 cls.file.modtime = pkg.default_modtime;
803 }
804
805 file_name.doneDisbursing();
806 file_size_hi.doneDisbursing();
807 file_size_lo.doneDisbursing();
808 file_modtime.doneDisbursing();
809 file_options.doneDisbursing();
810 file_bits.doneDisbursing();
811 file_bands.doneDisbursing();
812
813 if (archiveSize1 != 0 && !in.atLimit()) {
814 throw new RuntimeException("Predicted archive_size "+
815 archiveSize1+" != "+
816 (in.getBytesServed()-archiveSize0));
817 }
818 }
819
820 void readAttrDefs() throws IOException {
821
822
823
824
825 attr_definition_headers.expectLength(numAttrDefs);
826 attr_definition_name.expectLength(numAttrDefs);
827 attr_definition_layout.expectLength(numAttrDefs);
828 attr_definition_headers.readFrom(in);
829 attr_definition_name.readFrom(in);
830 attr_definition_layout.readFrom(in);
831 try (PrintStream dump = !optDumpBands ? null
832 : new PrintStream(getDumpStream(attr_definition_headers, ".def")))
833 {
834 for (int i = 0; i < numAttrDefs; i++) {
835 int header = attr_definition_headers.getByte();
836 Utf8Entry name = (Utf8Entry) attr_definition_name.getRef();
837 Utf8Entry layout = (Utf8Entry) attr_definition_layout.getRef();
838 int ctype = (header & ADH_CONTEXT_MASK);
839 int index = (header >> ADH_BIT_SHIFT) - ADH_BIT_IS_LSB;
840 Attribute.Layout def = new Attribute.Layout(ctype,
841 name.stringValue(),
842 layout.stringValue());
843
844 String pvLayout = def.layoutForPackageMajver(getPackageMajver());
845 if (!pvLayout.equals(def.layout())) {
846 throw new IOException("Bad attribute layout in version 150 archive: "+def.layout());
847 }
848 this.setAttributeLayoutIndex(def, index);
849 if (dump != null) dump.println(index+" "+def);
850 }
851 }
852 attr_definition_headers.doneDisbursing();
853 attr_definition_name.doneDisbursing();
854 attr_definition_layout.doneDisbursing();
855
856
857 makeNewAttributeBands();
858 attr_definition_bands.doneDisbursing();
859 }
860
861 void readInnerClasses() throws IOException {
862
863
864
865
866
867 ic_this_class.expectLength(numInnerClasses);
868 ic_this_class.readFrom(in);
869 ic_flags.expectLength(numInnerClasses);
870 ic_flags.readFrom(in);
871 int longICCount = 0;
872 for (int i = 0; i < numInnerClasses; i++) {
873 int flags = ic_flags.getInt();
874 boolean longForm = (flags & ACC_IC_LONG_FORM) != 0;
875 if (longForm) {
876 longICCount += 1;
877 }
878 }
879 ic_outer_class.expectLength(longICCount);
880 ic_outer_class.readFrom(in);
881 ic_name.expectLength(longICCount);
882 ic_name.readFrom(in);
883 ic_flags.resetForSecondPass();
884 List<InnerClass> icList = new ArrayList<>(numInnerClasses);
885 for (int i = 0; i < numInnerClasses; i++) {
886 int flags = ic_flags.getInt();
887 boolean longForm = (flags & ACC_IC_LONG_FORM) != 0;
888 flags &= ~ACC_IC_LONG_FORM;
889 ClassEntry thisClass = (ClassEntry) ic_this_class.getRef();
890 ClassEntry outerClass;
891 Utf8Entry thisName;
892 if (longForm) {
893 outerClass = (ClassEntry) ic_outer_class.getRef();
894 thisName = (Utf8Entry) ic_name.getRef();
895 } else {
896 String n = thisClass.stringValue();
897 String[] parse = Package.parseInnerClassName(n);
898 assert(parse != null);
899 String pkgOuter = parse[0];
900
901 String name = parse[2];
902 if (pkgOuter == null)
903 outerClass = null;
904 else
905 outerClass = ConstantPool.getClassEntry(pkgOuter);
906 if (name == null)
907 thisName = null;
908 else
909 thisName = ConstantPool.getUtf8Entry(name);
910 }
911 InnerClass ic =
912 new InnerClass(thisClass, outerClass, thisName, flags);
913 assert(longForm || ic.predictable);
914 icList.add(ic);
915 }
916 ic_flags.doneDisbursing();
917 ic_this_class.doneDisbursing();
918 ic_outer_class.doneDisbursing();
919 ic_name.doneDisbursing();
920 pkg.setAllInnerClasses(icList);
921 ic_bands.doneDisbursing();
922 }
923
924 void readLocalInnerClasses(Class cls) throws IOException {
925 int nc = class_InnerClasses_N.getInt();
926 List<InnerClass> localICs = new ArrayList<>(nc);
927 for (int i = 0; i < nc; i++) {
928 ClassEntry thisClass = (ClassEntry) class_InnerClasses_RC.getRef();
929 int flags = class_InnerClasses_F.getInt();
930 if (flags == 0) {
931
932 InnerClass ic = pkg.getGlobalInnerClass(thisClass);
933 assert(ic != null);
934 localICs.add(ic);
935 } else {
936 if (flags == ACC_IC_LONG_FORM)
937 flags = 0;
938 ClassEntry outer = (ClassEntry) class_InnerClasses_outer_RCN.getRef();
939 Utf8Entry name = (Utf8Entry) class_InnerClasses_name_RUN.getRef();
940 localICs.add(new InnerClass(thisClass, outer, name, flags));
941 }
942 }
943 cls.setInnerClasses(localICs);
944
945
946
947
948 }
949
950 static final int NO_FLAGS_YET = 0;
951
952 Class[] readClasses() throws IOException {
953
954
955
956
957
958
959
960
961 Class[] classes = new Class[numClasses];
962 if (verbose > 0)
963 Utils.log.info(" ...building "+classes.length+" classes...");
964
965 class_this.expectLength(numClasses);
966 class_super.expectLength(numClasses);
967 class_interface_count.expectLength(numClasses);
968
969 class_this.readFrom(in);
970 class_super.readFrom(in);
971 class_interface_count.readFrom(in);
972 class_interface.expectLength(class_interface_count.getIntTotal());
973 class_interface.readFrom(in);
974 for (int i = 0; i < classes.length; i++) {
975 ClassEntry thisClass = (ClassEntry) class_this.getRef();
976 ClassEntry superClass = (ClassEntry) class_super.getRef();
977 ClassEntry[] interfaces = new ClassEntry[class_interface_count.getInt()];
978 for (int j = 0; j < interfaces.length; j++) {
979 interfaces[j] = (ClassEntry) class_interface.getRef();
980 }
981
982 if (superClass == thisClass) superClass = null;
983 Class cls = pkg.new Class(NO_FLAGS_YET,
984 thisClass, superClass, interfaces);
985 classes[i] = cls;
986 }
987 class_this.doneDisbursing();
988 class_super.doneDisbursing();
989 class_interface_count.doneDisbursing();
990 class_interface.doneDisbursing();
991 readMembers(classes);
992 countAndReadAttrs(ATTR_CONTEXT_CLASS, Arrays.asList(classes));
993 pkg.trimToSize();
994 readCodeHeaders();
995
996
997 return classes;
998 }
999
1000 private int getOutputIndex(Entry e) {
1001
1002 assert(e.tag != CONSTANT_Signature);
1003 int k = pkg.cp.untypedIndexOf(e);
1004
1005
1006 if (k >= 0)
1007 return k;
1008 if (e.tag == CONSTANT_Utf8) {
1009 Entry se = (Entry) utf8Signatures.get(e);
1010 return pkg.cp.untypedIndexOf(se);
1011 }
1012 return -1;
1013 }
1014
1015 Comparator<Entry> entryOutputOrder = new Comparator<Entry>() {
1016 public int compare(Entry e0, Entry e1) {
1017 int k0 = getOutputIndex(e0);
1018 int k1 = getOutputIndex(e1);
1019 if (k0 >= 0 && k1 >= 0)
1020
1021 return k0 - k1;
1022 if (k0 == k1)
1023
1024 return e0.compareTo(e1);
1025
1026 return (k0 >= 0)? 0-1: 1-0;
1027 }
1028 };
1029
1030 void reconstructClass(Class cls) {
1031 if (verbose > 1) Utils.log.fine("reconstruct "+cls);
1032
1033
1034 Attribute retroVersion = cls.getAttribute(attrClassFileVersion);
1035 if (retroVersion != null) {
1036 cls.removeAttribute(retroVersion);
1037 short[] minmajver = parseClassFileVersionAttr(retroVersion);
1038 cls.minver = minmajver[0];
1039 cls.majver = minmajver[1];
1040 } else {
1041 cls.minver = pkg.default_class_minver;
1042 cls.majver = pkg.default_class_majver;
1043 }
1044
1045
1046 cls.expandSourceFile();
1047
1048
1049 cls.setCPMap(reconstructLocalCPMap(cls));
1050 }
1051
1052 Entry[] reconstructLocalCPMap(Class cls) {
1053 Set<Entry> ldcRefs = ldcRefMap.get(cls);
1054 Set<Entry> cpRefs = new HashSet<>();
1055
1056
1057 cls.visitRefs(VRM_CLASSIC, cpRefs);
1058
1059
1060 ConstantPool.completeReferencesIn(cpRefs, true);
1061
1062
1063
1064 int changed = cls.expandLocalICs();
1065
1066 if (changed != 0) {
1067 if (changed > 0) {
1068
1069 cls.visitInnerClassRefs(VRM_CLASSIC, cpRefs);
1070 } else {
1071
1072 cpRefs.clear();
1073 cls.visitRefs(VRM_CLASSIC, cpRefs);
1074 }
1075
1076
1077 ConstantPool.completeReferencesIn(cpRefs, true);
1078 }
1079
1080
1081 int numDoubles = 0;
1082 for (Entry e : cpRefs) {
1083 if (e.isDoubleWord()) numDoubles++;
1084 assert(e.tag != CONSTANT_Signature) : (e);
1085 }
1086 Entry[] cpMap = new Entry[1+numDoubles+cpRefs.size()];
1087 int fillp = 1;
1088
1089
1090 if (ldcRefs != null) {
1091 assert(cpRefs.containsAll(ldcRefs));
1092 for (Entry e : ldcRefs) {
1093 cpMap[fillp++] = e;
1094 }
1095 assert(fillp == 1+ldcRefs.size());
1096 cpRefs.removeAll(ldcRefs);
1097 ldcRefs = null;
1098 }
1099
1100
1101 Set<Entry> wideRefs = cpRefs;
1102 cpRefs = null;
1103 int narrowLimit = fillp;
1104 for (Entry e : wideRefs) {
1105 cpMap[fillp++] = e;
1106 }
1107 assert(fillp == narrowLimit+wideRefs.size());
1108 Arrays.sort(cpMap, 1, narrowLimit, entryOutputOrder);
1109 Arrays.sort(cpMap, narrowLimit, fillp, entryOutputOrder);
1110
1111 if (verbose > 3) {
1112 Utils.log.fine("CP of "+this+" {");
1113 for (int i = 0; i < fillp; i++) {
1114 Entry e = cpMap[i];
1115 Utils.log.fine(" "+((e==null)?-1:getOutputIndex(e))
1116 +" : "+e);
1117 }
1118 Utils.log.fine("}");
1119 }
1120
1121
1122 int revp = cpMap.length;
1123 for (int i = fillp; --i >= 1; ) {
1124 Entry e = cpMap[i];
1125 if (e.isDoubleWord())
1126 cpMap[--revp] = null;
1127 cpMap[--revp] = e;
1128 }
1129 assert(revp == 1);
1130
1131 return cpMap;
1132 }
1133
1134 void readMembers(Class[] classes) throws IOException {
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146 assert(classes.length == numClasses);
1147 class_field_count.expectLength(numClasses);
1148 class_method_count.expectLength(numClasses);
1149 class_field_count.readFrom(in);
1150 class_method_count.readFrom(in);
1151
1152
1153 int totalNF = class_field_count.getIntTotal();
1154 int totalNM = class_method_count.getIntTotal();
1155 field_descr.expectLength(totalNF);
1156 method_descr.expectLength(totalNM);
1157 if (verbose > 1) Utils.log.fine("expecting #fields="+totalNF+" and #methods="+totalNM+" in #classes="+numClasses);
1158
1159 List<Class.Field> fields = new ArrayList<>(totalNF);
1160 field_descr.readFrom(in);
1161 for (int i = 0; i < classes.length; i++) {
1162 Class c = classes[i];
1163 int nf = class_field_count.getInt();
1164 for (int j = 0; j < nf; j++) {
1165 Class.Field f = c.new Field(NO_FLAGS_YET, (DescriptorEntry)
1166 field_descr.getRef());
1167 fields.add(f);
1168 }
1169 }
1170 class_field_count.doneDisbursing();
1171 field_descr.doneDisbursing();
1172 countAndReadAttrs(ATTR_CONTEXT_FIELD, fields);
1173 fields = null;
1174
1175 List<Class.Method> methods = new ArrayList<>(totalNM);
1176 method_descr.readFrom(in);
1177 for (int i = 0; i < classes.length; i++) {
1178 Class c = classes[i];
1179 int nm = class_method_count.getInt();
1180 for (int j = 0; j < nm; j++) {
1181 Class.Method m = c.new Method(NO_FLAGS_YET, (DescriptorEntry)
1182 method_descr.getRef());
1183 methods.add(m);
1184 }
1185 }
1186 class_method_count.doneDisbursing();
1187 method_descr.doneDisbursing();
1188 countAndReadAttrs(ATTR_CONTEXT_METHOD, methods);
1189
1190
1191
1192
1193 allCodes = buildCodeAttrs(methods);
1194 }
1195
1196 Code[] allCodes;
1197 List<Code> codesWithFlags;
1198 Map<Class, Set<Entry>> ldcRefMap = new HashMap<>();
1199
1200 Code[] buildCodeAttrs(List<Class.Method> methods) {
1201 List<Code> codes = new ArrayList<>(methods.size());
1202 for (Class.Method m : methods) {
1203 if (m.getAttribute(attrCodeEmpty) != null) {
1204 m.code = new Code(m);
1205 codes.add(m.code);
1206 }
1207 }
1208 Code[] a = new Code[codes.size()];
1209 codes.toArray(a);
1210 return a;
1211 }
1212
1213 void readCodeHeaders() throws IOException {
1214
1215
1216
1217
1218
1219
1220
1221
1222 boolean attrsOK = testBit(archiveOptions, AO_HAVE_ALL_CODE_FLAGS);
1223 code_headers.expectLength(allCodes.length);
1224 code_headers.readFrom(in);
1225 List<Code> longCodes = new ArrayList<>(allCodes.length / 10);
1226 for (int i = 0; i < allCodes.length; i++) {
1227 Code c = allCodes[i];
1228 int sc = code_headers.getByte();
1229 assert(sc == (sc & 0xFF));
1230 if (verbose > 2)
1231 Utils.log.fine("codeHeader "+c+" = "+sc);
1232 if (sc == LONG_CODE_HEADER) {
1233
1234 longCodes.add(c);
1235 continue;
1236 }
1237
1238 c.setMaxStack( shortCodeHeader_max_stack(sc) );
1239 c.setMaxNALocals( shortCodeHeader_max_na_locals(sc) );
1240 c.setHandlerCount( shortCodeHeader_handler_count(sc) );
1241 assert(shortCodeHeader(c) == sc);
1242 }
1243 code_headers.doneDisbursing();
1244 code_max_stack.expectLength(longCodes.size());
1245 code_max_na_locals.expectLength(longCodes.size());
1246 code_handler_count.expectLength(longCodes.size());
1247
1248
1249 code_max_stack.readFrom(in);
1250 code_max_na_locals.readFrom(in);
1251 code_handler_count.readFrom(in);
1252 for (Code c : longCodes) {
1253 c.setMaxStack( code_max_stack.getInt() );
1254 c.setMaxNALocals( code_max_na_locals.getInt() );
1255 c.setHandlerCount( code_handler_count.getInt() );
1256 }
1257 code_max_stack.doneDisbursing();
1258 code_max_na_locals.doneDisbursing();
1259 code_handler_count.doneDisbursing();
1260
1261 readCodeHandlers();
1262
1263 if (attrsOK) {
1264
1265 codesWithFlags = Arrays.asList(allCodes);
1266 } else {
1267
1268 codesWithFlags = longCodes;
1269 }
1270 countAttrs(ATTR_CONTEXT_CODE, codesWithFlags);
1271
1272 }
1273
1274 void readCodeHandlers() throws IOException {
1275
1276
1277
1278
1279
1280
1281
1282 int nh = 0;
1283 for (int i = 0; i < allCodes.length; i++) {
1284 Code c = allCodes[i];
1285 nh += c.getHandlerCount();
1286 }
1287
1288 ValueBand[] code_handler_bands = {
1289 code_handler_start_P,
1290 code_handler_end_PO,
1291 code_handler_catch_PO,
1292 code_handler_class_RCN
1293 };
1294
1295 for (int i = 0; i < code_handler_bands.length; i++) {
1296 code_handler_bands[i].expectLength(nh);
1297 code_handler_bands[i].readFrom(in);
1298 }
1299
1300 for (int i = 0; i < allCodes.length; i++) {
1301 Code c = allCodes[i];
1302 for (int j = 0, jmax = c.getHandlerCount(); j < jmax; j++) {
1303 c.handler_class[j] = code_handler_class_RCN.getRef();
1304
1305
1306 c.handler_start[j] = code_handler_start_P.getInt();
1307 c.handler_end[j] = code_handler_end_PO.getInt();
1308 c.handler_catch[j] = code_handler_catch_PO.getInt();
1309 }
1310 }
1311 for (int i = 0; i < code_handler_bands.length; i++) {
1312 code_handler_bands[i].doneDisbursing();
1313 }
1314 }
1315
1316 void fixupCodeHandlers() {
1317
1318 for (int i = 0; i < allCodes.length; i++) {
1319 Code c = allCodes[i];
1320 for (int j = 0, jmax = c.getHandlerCount(); j < jmax; j++) {
1321 int sum = c.handler_start[j];
1322 c.handler_start[j] = c.decodeBCI(sum);
1323 sum += c.handler_end[j];
1324 c.handler_end[j] = c.decodeBCI(sum);
1325 sum += c.handler_catch[j];
1326 c.handler_catch[j] = c.decodeBCI(sum);
1327 }
1328 }
1329 }
1330
1331
1332
1333
1334
1335 void countAndReadAttrs(int ctype, Collection holders) throws IOException {
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383 countAttrs(ctype, holders);
1384 readAttrs(ctype, holders);
1385 }
1386
1387
1388
1389 void countAttrs(int ctype, Collection holders) throws IOException {
1390
1391 MultiBand xxx_attr_bands = attrBands[ctype];
1392 long flagMask = attrFlagMask[ctype];
1393 if (verbose > 1) {
1394 Utils.log.fine("scanning flags and attrs for "+Attribute.contextName(ctype)+"["+holders.size()+"]");
1395 }
1396
1397
1398
1399 List<Attribute.Layout> defList = attrDefs.get(ctype);
1400 Attribute.Layout[] defs = new Attribute.Layout[defList.size()];
1401 defList.toArray(defs);
1402 IntBand xxx_flags_hi = getAttrBand(xxx_attr_bands, AB_FLAGS_HI);
1403 IntBand xxx_flags_lo = getAttrBand(xxx_attr_bands, AB_FLAGS_LO);
1404 IntBand xxx_attr_count = getAttrBand(xxx_attr_bands, AB_ATTR_COUNT);
1405 IntBand xxx_attr_indexes = getAttrBand(xxx_attr_bands, AB_ATTR_INDEXES);
1406 IntBand xxx_attr_calls = getAttrBand(xxx_attr_bands, AB_ATTR_CALLS);
1407
1408
1409 int overflowMask = attrOverflowMask[ctype];
1410 int overflowHolderCount = 0;
1411 boolean haveLongFlags = haveFlagsHi(ctype);
1412 xxx_flags_hi.expectLength(haveLongFlags? holders.size(): 0);
1413 xxx_flags_hi.readFrom(in);
1414 xxx_flags_lo.expectLength(holders.size());
1415 xxx_flags_lo.readFrom(in);
1416 assert((flagMask & overflowMask) == overflowMask);
1417 for (Iterator i = holders.iterator(); i.hasNext(); ) {
1418 Attribute.Holder h = (Attribute.Holder) i.next();
1419 int flags = xxx_flags_lo.getInt();
1420 h.flags = flags;
1421 if ((flags & overflowMask) != 0)
1422 overflowHolderCount += 1;
1423 }
1424
1425
1426 xxx_attr_count.expectLength(overflowHolderCount);
1427 xxx_attr_count.readFrom(in);
1428 xxx_attr_indexes.expectLength(xxx_attr_count.getIntTotal());
1429 xxx_attr_indexes.readFrom(in);
1430
1431
1432
1433
1434
1435 int[] totalCounts = new int[defs.length];
1436 for (Iterator i = holders.iterator(); i.hasNext(); ) {
1437 Attribute.Holder h = (Attribute.Holder) i.next();
1438 assert(h.attributes == null);
1439
1440 long attrBits = ((h.flags & flagMask) << 32) >>> 32;
1441
1442 h.flags -= (int)attrBits;
1443 assert(h.flags == (char)h.flags);
1444 assert((ctype != ATTR_CONTEXT_CODE) || h.flags == 0);
1445 if (haveLongFlags)
1446 attrBits += (long)xxx_flags_hi.getInt() << 32;
1447 if (attrBits == 0) continue;
1448
1449 int noa = 0;
1450 long overflowBit = (attrBits & overflowMask);
1451 assert(overflowBit >= 0);
1452 attrBits -= overflowBit;
1453 if (overflowBit != 0) {
1454 noa = xxx_attr_count.getInt();
1455 }
1456
1457 int nfa = 0;
1458 long bits = attrBits;
1459 for (int ai = 0; bits != 0; ai++) {
1460 if ((bits & (1L<<ai)) == 0) continue;
1461 bits -= (1L<<ai);
1462 nfa += 1;
1463 }
1464 List<Attribute> ha = new ArrayList<>(nfa + noa);
1465 h.attributes = ha;
1466 bits = attrBits;
1467 for (int ai = 0; bits != 0; ai++) {
1468 if ((bits & (1L<<ai)) == 0) continue;
1469 bits -= (1L<<ai);
1470 totalCounts[ai] += 1;
1471
1472 if (defs[ai] == null) badAttrIndex(ai, ctype);
1473 Attribute canonical = defs[ai].canonicalInstance();
1474 ha.add(canonical);
1475 nfa -= 1;
1476 }
1477 assert(nfa == 0);
1478 for (; noa > 0; noa--) {
1479 int ai = xxx_attr_indexes.getInt();
1480 totalCounts[ai] += 1;
1481
1482 if (defs[ai] == null) badAttrIndex(ai, ctype);
1483 Attribute canonical = defs[ai].canonicalInstance();
1484 ha.add(canonical);
1485 }
1486 }
1487
1488 xxx_flags_hi.doneDisbursing();
1489 xxx_flags_lo.doneDisbursing();
1490 xxx_attr_count.doneDisbursing();
1491 xxx_attr_indexes.doneDisbursing();
1492
1493
1494
1495
1496
1497
1498
1499
1500 int callCounts = 0;
1501 for (boolean predef = true; ; predef = false) {
1502 for (int ai = 0; ai < defs.length; ai++) {
1503 Attribute.Layout def = defs[ai];
1504 if (def == null) continue;
1505 if (predef != isPredefinedAttr(ctype, ai))
1506 continue;
1507 int totalCount = totalCounts[ai];
1508 if (totalCount == 0)
1509 continue;
1510 Attribute.Layout.Element[] cbles = def.getCallables();
1511 for (int j = 0; j < cbles.length; j++) {
1512 assert(cbles[j].kind == Attribute.EK_CBLE);
1513 if (cbles[j].flagTest(Attribute.EF_BACK))
1514 callCounts += 1;
1515 }
1516 }
1517 if (!predef) break;
1518 }
1519 xxx_attr_calls.expectLength(callCounts);
1520 xxx_attr_calls.readFrom(in);
1521
1522
1523 for (boolean predef = true; ; predef = false) {
1524 for (int ai = 0; ai < defs.length; ai++) {
1525 Attribute.Layout def = defs[ai];
1526 if (def == null) continue;
1527 if (predef != isPredefinedAttr(ctype, ai))
1528 continue;
1529 int totalCount = totalCounts[ai];
1530 Band[] ab = attrBandTable.get(def);
1531 if (def == attrInnerClassesEmpty) {
1532
1533
1534
1535 class_InnerClasses_N.expectLength(totalCount);
1536 class_InnerClasses_N.readFrom(in);
1537 int tupleCount = class_InnerClasses_N.getIntTotal();
1538 class_InnerClasses_RC.expectLength(tupleCount);
1539 class_InnerClasses_RC.readFrom(in);
1540 class_InnerClasses_F.expectLength(tupleCount);
1541 class_InnerClasses_F.readFrom(in);
1542
1543 tupleCount -= class_InnerClasses_F.getIntCount(0);
1544 class_InnerClasses_outer_RCN.expectLength(tupleCount);
1545 class_InnerClasses_outer_RCN.readFrom(in);
1546 class_InnerClasses_name_RUN.expectLength(tupleCount);
1547 class_InnerClasses_name_RUN.readFrom(in);
1548 } else if (totalCount == 0) {
1549
1550 for (int j = 0; j < ab.length; j++) {
1551 ab[j].doneWithUnusedBand();
1552 }
1553 } else {
1554
1555 boolean hasCallables = def.hasCallables();
1556 if (!hasCallables) {
1557 readAttrBands(def.elems, totalCount, new int[0], ab);
1558 } else {
1559 Attribute.Layout.Element[] cbles = def.getCallables();
1560
1561
1562 int[] forwardCounts = new int[cbles.length];
1563 forwardCounts[0] = totalCount;
1564 for (int j = 0; j < cbles.length; j++) {
1565 assert(cbles[j].kind == Attribute.EK_CBLE);
1566 int entryCount = forwardCounts[j];
1567 forwardCounts[j] = -1;
1568 if (cbles[j].flagTest(Attribute.EF_BACK))
1569 entryCount += xxx_attr_calls.getInt();
1570 readAttrBands(cbles[j].body, entryCount, forwardCounts, ab);
1571 }
1572 }
1573 }
1574 }
1575 if (!predef) break;
1576 }
1577 xxx_attr_calls.doneDisbursing();
1578 }
1579
1580 void badAttrIndex(int ai, int ctype) throws IOException {
1581 throw new IOException("Unknown attribute index "+ai+" for "+
1582 ATTR_CONTEXT_NAME[ctype]+" attribute");
1583 }
1584
1585 @SuppressWarnings("unchecked")
1586 void readAttrs(int ctype, Collection holders) throws IOException {
1587
1588 Set<Attribute.Layout> sawDefs = new HashSet<>();
1589 ByteArrayOutputStream buf = new ByteArrayOutputStream();
1590 for (Iterator i = holders.iterator(); i.hasNext(); ) {
1591 final Attribute.Holder h = (Attribute.Holder) i.next();
1592 if (h.attributes == null) continue;
1593 for (ListIterator<Attribute> j = h.attributes.listIterator(); j.hasNext(); ) {
1594 Attribute a = j.next();
1595 Attribute.Layout def = a.layout();
1596 if (def.bandCount == 0) {
1597 if (def == attrInnerClassesEmpty) {
1598
1599 readLocalInnerClasses((Class) h);
1600 continue;
1601 }
1602
1603 continue;
1604 }
1605 sawDefs.add(def);
1606 boolean isCV = (ctype == ATTR_CONTEXT_FIELD && def == attrConstantValue);
1607 if (isCV) setConstantValueIndex((Class.Field)h);
1608 if (verbose > 2)
1609 Utils.log.fine("read "+a+" in "+h);
1610 final Band[] ab = attrBandTable.get(def);
1611
1612 buf.reset();
1613 Object fixups = a.unparse(new Attribute.ValueStream() {
1614 public int getInt(int bandIndex) {
1615 return ((IntBand) ab[bandIndex]).getInt();
1616 }
1617 public Entry getRef(int bandIndex) {
1618 return ((CPRefBand) ab[bandIndex]).getRef();
1619 }
1620 public int decodeBCI(int bciCode) {
1621 Code code = (Code) h;
1622 return code.decodeBCI(bciCode);
1623 }
1624 }, buf);
1625
1626 j.set(a.addContent(buf.toByteArray(), fixups));
1627 if (isCV) setConstantValueIndex(null);
1628 }
1629 }
1630
1631
1632 for (Attribute.Layout def : sawDefs) {
1633 if (def == null) continue;
1634 Band[] ab = attrBandTable.get(def);
1635 for (int j = 0; j < ab.length; j++) {
1636 ab[j].doneDisbursing();
1637 }
1638 }
1639
1640 if (ctype == ATTR_CONTEXT_CLASS) {
1641 class_InnerClasses_N.doneDisbursing();
1642 class_InnerClasses_RC.doneDisbursing();
1643 class_InnerClasses_F.doneDisbursing();
1644 class_InnerClasses_outer_RCN.doneDisbursing();
1645 class_InnerClasses_name_RUN.doneDisbursing();
1646 }
1647
1648 MultiBand xxx_attr_bands = attrBands[ctype];
1649 for (int i = 0; i < xxx_attr_bands.size(); i++) {
1650 Band b = xxx_attr_bands.get(i);
1651 if (b instanceof MultiBand)
1652 b.doneDisbursing();
1653 }
1654 xxx_attr_bands.doneDisbursing();
1655 }
1656
1657 private
1658 void readAttrBands(Attribute.Layout.Element[] elems,
1659 int count, int[] forwardCounts,
1660 Band[] ab)
1661 throws IOException {
1662 for (int i = 0; i < elems.length; i++) {
1663 Attribute.Layout.Element e = elems[i];
1664 Band eBand = null;
1665 if (e.hasBand()) {
1666 eBand = ab[e.bandIndex];
1667 eBand.expectLength(count);
1668 eBand.readFrom(in);
1669 }
1670 switch (e.kind) {
1671 case Attribute.EK_REPL:
1672
1673 int repCount = ((IntBand)eBand).getIntTotal();
1674
1675 readAttrBands(e.body, repCount, forwardCounts, ab);
1676 break;
1677 case Attribute.EK_UN:
1678 int remainingCount = count;
1679 for (int j = 0; j < e.body.length; j++) {
1680 int caseCount;
1681 if (j == e.body.length-1) {
1682 caseCount = remainingCount;
1683 } else {
1684 caseCount = 0;
1685 for (int j0 = j;
1686 (j == j0)
1687 || (j < e.body.length
1688 && e.body[j].flagTest(Attribute.EF_BACK));
1689 j++) {
1690 caseCount += ((IntBand)eBand).getIntCount(e.body[j].value);
1691 }
1692 --j;
1693 }
1694 remainingCount -= caseCount;
1695 readAttrBands(e.body[j].body, caseCount, forwardCounts, ab);
1696 }
1697 assert(remainingCount == 0);
1698 break;
1699 case Attribute.EK_CALL:
1700 assert(e.body.length == 1);
1701 assert(e.body[0].kind == Attribute.EK_CBLE);
1702 if (!e.flagTest(Attribute.EF_BACK)) {
1703
1704
1705 assert(forwardCounts[e.value] >= 0);
1706 forwardCounts[e.value] += count;
1707 }
1708 break;
1709 case Attribute.EK_CBLE:
1710 assert(false);
1711 break;
1712 }
1713 }
1714 }
1715
1716 void readByteCodes() throws IOException {
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743 bc_codes.elementCountForDebug = allCodes.length;
1744 bc_codes.setInputStreamFrom(in);
1745 readByteCodeOps();
1746 bc_codes.doneDisbursing();
1747
1748
1749 Band[] operand_bands = {
1750 bc_case_value,
1751 bc_byte, bc_short,
1752 bc_local, bc_label,
1753 bc_intref, bc_floatref,
1754 bc_longref, bc_doubleref, bc_stringref,
1755 bc_classref, bc_fieldref,
1756 bc_methodref, bc_imethodref,
1757 bc_thisfield, bc_superfield,
1758 bc_thismethod, bc_supermethod,
1759 bc_initref,
1760 bc_escref, bc_escrefsize, bc_escsize
1761 };
1762 for (int i = 0; i < operand_bands.length; i++) {
1763 operand_bands[i].readFrom(in);
1764 }
1765 bc_escbyte.expectLength(bc_escsize.getIntTotal());
1766 bc_escbyte.readFrom(in);
1767
1768 expandByteCodeOps();
1769
1770
1771 bc_case_count.doneDisbursing();
1772 for (int i = 0; i < operand_bands.length; i++) {
1773 operand_bands[i].doneDisbursing();
1774 }
1775 bc_escbyte.doneDisbursing();
1776 bc_bands.doneDisbursing();
1777
1778
1779
1780 readAttrs(ATTR_CONTEXT_CODE, codesWithFlags);
1781
1782 fixupCodeHandlers();
1783
1784 code_bands.doneDisbursing();
1785 class_bands.doneDisbursing();
1786 }
1787
1788 private void readByteCodeOps() throws IOException {
1789
1790 byte[] buf = new byte[1<<12];
1791
1792 List<Integer> allSwitchOps = new ArrayList<>();
1793 for (int k = 0; k < allCodes.length; k++) {
1794 Code c = allCodes[k];
1795 scanOneMethod:
1796 for (int i = 0; ; i++) {
1797 int bc = bc_codes.getByte();
1798 if (i + 10 > buf.length) buf = realloc(buf);
1799 buf[i] = (byte)bc;
1800 boolean isWide = false;
1801 if (bc == _wide) {
1802 bc = bc_codes.getByte();
1803 buf[++i] = (byte)bc;
1804 isWide = true;
1805 }
1806 assert(bc == (0xFF & bc));
1807
1808 switch (bc) {
1809 case _tableswitch:
1810 case _lookupswitch:
1811 bc_case_count.expectMoreLength(1);
1812 allSwitchOps.add(bc);
1813 break;
1814 case _iinc:
1815 bc_local.expectMoreLength(1);
1816 if (isWide)
1817 bc_short.expectMoreLength(1);
1818 else
1819 bc_byte.expectMoreLength(1);
1820 break;
1821 case _sipush:
1822 bc_short.expectMoreLength(1);
1823 break;
1824 case _bipush:
1825 bc_byte.expectMoreLength(1);
1826 break;
1827 case _newarray:
1828 bc_byte.expectMoreLength(1);
1829 break;
1830 case _multianewarray:
1831 assert(getCPRefOpBand(bc) == bc_classref);
1832 bc_classref.expectMoreLength(1);
1833 bc_byte.expectMoreLength(1);
1834 break;
1835 case _ref_escape:
1836 bc_escrefsize.expectMoreLength(1);
1837 bc_escref.expectMoreLength(1);
1838 break;
1839 case _byte_escape:
1840 bc_escsize.expectMoreLength(1);
1841
1842 break;
1843 default:
1844 if (Instruction.isInvokeInitOp(bc)) {
1845 bc_initref.expectMoreLength(1);
1846 break;
1847 }
1848 if (Instruction.isSelfLinkerOp(bc)) {
1849 CPRefBand bc_which = selfOpRefBand(bc);
1850 bc_which.expectMoreLength(1);
1851 break;
1852 }
1853 if (Instruction.isBranchOp(bc)) {
1854 bc_label.expectMoreLength(1);
1855 break;
1856 }
1857 if (Instruction.isCPRefOp(bc)) {
1858 CPRefBand bc_which = getCPRefOpBand(bc);
1859 bc_which.expectMoreLength(1);
1860 assert(bc != _multianewarray);
1861 break;
1862 }
1863 if (Instruction.isLocalSlotOp(bc)) {
1864 bc_local.expectMoreLength(1);
1865 break;
1866 }
1867 break;
1868 case _end_marker:
1869 {
1870
1871 c.bytes = realloc(buf, i);
1872 break scanOneMethod;
1873 }
1874 }
1875 }
1876 }
1877
1878
1879 bc_case_count.readFrom(in);
1880 for (Integer i : allSwitchOps) {
1881 int bc = i.intValue();
1882 int caseCount = bc_case_count.getInt();
1883 bc_label.expectMoreLength(1+caseCount);
1884 bc_case_value.expectMoreLength(bc == _tableswitch ? 1 : caseCount);
1885 }
1886 bc_case_count.resetForSecondPass();
1887 }
1888
1889 private void expandByteCodeOps() throws IOException {
1890
1891 byte[] buf = new byte[1<<12];
1892
1893 int[] insnMap = new int[1<<12];
1894
1895 int[] labels = new int[1<<10];
1896
1897 Fixups fixupBuf = new Fixups();
1898
1899 for (int k = 0; k < allCodes.length; k++) {
1900 Code code = allCodes[k];
1901 byte[] codeOps = code.bytes;
1902 code.bytes = null;
1903
1904 Class curClass = code.thisClass();
1905
1906 Set<Entry> ldcRefSet = ldcRefMap.get(curClass);
1907 if (ldcRefSet == null)
1908 ldcRefMap.put(curClass, ldcRefSet = new HashSet<>());
1909
1910 ClassEntry thisClass = curClass.thisClass;
1911 ClassEntry superClass = curClass.superClass;
1912 ClassEntry newClass = null;
1913
1914 int pc = 0;
1915 int numInsns = 0;
1916 int numLabels = 0;
1917 boolean hasEscs = false;
1918 fixupBuf.clear();
1919 for (int i = 0; i < codeOps.length; i++) {
1920 int bc = Instruction.getByte(codeOps, i);
1921 int curPC = pc;
1922 insnMap[numInsns++] = curPC;
1923 if (pc + 10 > buf.length) buf = realloc(buf);
1924 if (numInsns+10 > insnMap.length) insnMap = realloc(insnMap);
1925 if (numLabels+10 > labels.length) labels = realloc(labels);
1926 boolean isWide = false;
1927 if (bc == _wide) {
1928 buf[pc++] = (byte) bc;
1929 bc = Instruction.getByte(codeOps, ++i);
1930 isWide = true;
1931 }
1932 switch (bc) {
1933 case _tableswitch:
1934 case _lookupswitch:
1935 {
1936 int caseCount = bc_case_count.getInt();
1937 while ((pc + 30 + caseCount*8) > buf.length)
1938 buf = realloc(buf);
1939 buf[pc++] = (byte) bc;
1940
1941 Arrays.fill(buf, pc, pc+30, (byte)0);
1942 Instruction.Switch isw = (Instruction.Switch)
1943 Instruction.at(buf, curPC);
1944
1945 isw.setCaseCount(caseCount);
1946 if (bc == _tableswitch) {
1947 isw.setCaseValue(0, bc_case_value.getInt());
1948 } else {
1949 for (int j = 0; j < caseCount; j++) {
1950 isw.setCaseValue(j, bc_case_value.getInt());
1951 }
1952 }
1953
1954 labels[numLabels++] = curPC;
1955 pc = isw.getNextPC();
1956 continue;
1957 }
1958 case _iinc:
1959 {
1960 buf[pc++] = (byte) bc;
1961 int local = bc_local.getInt();
1962 int delta;
1963 if (isWide) {
1964 delta = bc_short.getInt();
1965 Instruction.setShort(buf, pc, local); pc += 2;
1966 Instruction.setShort(buf, pc, delta); pc += 2;
1967 } else {
1968 delta = (byte) bc_byte.getByte();
1969 buf[pc++] = (byte)local;
1970 buf[pc++] = (byte)delta;
1971 }
1972 continue;
1973 }
1974 case _sipush:
1975 {
1976 int val = bc_short.getInt();
1977 buf[pc++] = (byte) bc;
1978 Instruction.setShort(buf, pc, val); pc += 2;
1979 continue;
1980 }
1981 case _bipush:
1982 case _newarray:
1983 {
1984 int val = bc_byte.getByte();
1985 buf[pc++] = (byte) bc;
1986 buf[pc++] = (byte) val;
1987 continue;
1988 }
1989 case _ref_escape:
1990 {
1991
1992 hasEscs = true;
1993 int size = bc_escrefsize.getInt();
1994 Entry ref = bc_escref.getRef();
1995 if (size == 1) ldcRefSet.add(ref);
1996 int fmt;
1997 switch (size) {
1998 case 1: fmt = Fixups.U1_FORMAT; break;
1999 case 2: fmt = Fixups.U2_FORMAT; break;
2000 default: assert(false); fmt = 0;
2001 }
2002 fixupBuf.add(pc, fmt, ref);
2003 buf[pc+0] = buf[pc+1] = 0;
2004 pc += size;
2005 }
2006 continue;
2007 case _byte_escape:
2008 {
2009
2010 hasEscs = true;
2011 int size = bc_escsize.getInt();
2012 while ((pc + size) > buf.length)
2013 buf = realloc(buf);
2014 while (size-- > 0) {
2015 buf[pc++] = (byte) bc_escbyte.getByte();
2016 }
2017 }
2018 continue;
2019 default:
2020 if (Instruction.isInvokeInitOp(bc)) {
2021 int idx = (bc - _invokeinit_op);
2022 int origBC = _invokespecial;
2023 ClassEntry classRef;
2024 switch (idx) {
2025 case _invokeinit_self_option:
2026 classRef = thisClass; break;
2027 case _invokeinit_super_option:
2028 classRef = superClass; break;
2029 default:
2030 assert(idx == _invokeinit_new_option);
2031 classRef = newClass; break;
2032 }
2033 buf[pc++] = (byte) origBC;
2034 int coding = bc_initref.getInt();
2035
2036 MemberEntry ref = pkg.cp.getOverloadingForIndex(CONSTANT_Methodref, classRef, "<init>", coding);
2037 fixupBuf.add(pc, Fixups.U2_FORMAT, ref);
2038 buf[pc+0] = buf[pc+1] = 0;
2039 pc += 2;
2040 assert(Instruction.opLength(origBC) == (pc - curPC));
2041 continue;
2042 }
2043 if (Instruction.isSelfLinkerOp(bc)) {
2044 int idx = (bc - _self_linker_op);
2045 boolean isSuper = (idx >= _self_linker_super_flag);
2046 if (isSuper) idx -= _self_linker_super_flag;
2047 boolean isAload = (idx >= _self_linker_aload_flag);
2048 if (isAload) idx -= _self_linker_aload_flag;
2049 int origBC = _first_linker_op + idx;
2050 boolean isField = Instruction.isFieldOp(origBC);
2051 CPRefBand bc_which;
2052 ClassEntry which_cls = isSuper ? superClass : thisClass;
2053 Index which_ix;
2054 if (isField) {
2055 bc_which = isSuper ? bc_superfield : bc_thisfield;
2056 which_ix = pkg.cp.getMemberIndex(CONSTANT_Fieldref, which_cls);
2057 } else {
2058 bc_which = isSuper ? bc_supermethod : bc_thismethod;
2059 which_ix = pkg.cp.getMemberIndex(CONSTANT_Methodref, which_cls);
2060 }
2061 assert(bc_which == selfOpRefBand(bc));
2062 MemberEntry ref = (MemberEntry) bc_which.getRef(which_ix);
2063 if (isAload) {
2064 buf[pc++] = (byte) _aload_0;
2065 curPC = pc;
2066
2067 insnMap[numInsns++] = curPC;
2068 }
2069 buf[pc++] = (byte) origBC;
2070 fixupBuf.add(pc, Fixups.U2_FORMAT, ref);
2071 buf[pc+0] = buf[pc+1] = 0;
2072 pc += 2;
2073 assert(Instruction.opLength(origBC) == (pc - curPC));
2074 continue;
2075 }
2076 if (Instruction.isBranchOp(bc)) {
2077 buf[pc++] = (byte) bc;
2078 assert(!isWide);
2079 int nextPC = curPC + Instruction.opLength(bc);
2080
2081 labels[numLabels++] = curPC;
2082
2083 while (pc < nextPC) buf[pc++] = 0;
2084 continue;
2085 }
2086 if (Instruction.isCPRefOp(bc)) {
2087 CPRefBand bc_which = getCPRefOpBand(bc);
2088 Entry ref = bc_which.getRef();
2089 if (ref == null) {
2090 if (bc_which == bc_classref) {
2091
2092 ref = thisClass;
2093 } else {
2094 assert(false);
2095 }
2096 }
2097 int origBC = bc;
2098 int size = 2;
2099 switch (bc) {
2100 case _ildc:
2101 case _cldc:
2102 case _fldc:
2103 case _aldc:
2104 origBC = _ldc;
2105 size = 1;
2106 ldcRefSet.add(ref);
2107 break;
2108 case _ildc_w:
2109 case _cldc_w:
2110 case _fldc_w:
2111 case _aldc_w:
2112 origBC = _ldc_w;
2113 break;
2114 case _lldc2_w:
2115 case _dldc2_w:
2116 origBC = _ldc2_w;
2117 break;
2118 case _new:
2119 newClass = (ClassEntry) ref;
2120 break;
2121 }
2122 buf[pc++] = (byte) origBC;
2123 int fmt;
2124 switch (size) {
2125 case 1: fmt = Fixups.U1_FORMAT; break;
2126 case 2: fmt = Fixups.U2_FORMAT; break;
2127 default: assert(false); fmt = 0;
2128 }
2129 fixupBuf.add(pc, fmt, ref);
2130 buf[pc+0] = buf[pc+1] = 0;
2131 pc += size;
2132 if (origBC == _multianewarray) {
2133
2134 int val = bc_byte.getByte();
2135 buf[pc++] = (byte) val;
2136 } else if (origBC == _invokeinterface) {
2137 int argSize = ((MemberEntry)ref).descRef.typeRef.computeSize(true);
2138 buf[pc++] = (byte)( 1 + argSize );
2139 buf[pc++] = 0;
2140 }
2141 assert(Instruction.opLength(origBC) == (pc - curPC));
2142 continue;
2143 }
2144 if (Instruction.isLocalSlotOp(bc)) {
2145 buf[pc++] = (byte) bc;
2146 int local = bc_local.getInt();
2147 if (isWide) {
2148 Instruction.setShort(buf, pc, local);
2149 pc += 2;
2150 if (bc == _iinc) {
2151 int iVal = bc_short.getInt();
2152 Instruction.setShort(buf, pc, iVal);
2153 pc += 2;
2154 }
2155 } else {
2156 Instruction.setByte(buf, pc, local);
2157 pc += 1;
2158 if (bc == _iinc) {
2159 int iVal = bc_byte.getByte();
2160 Instruction.setByte(buf, pc, iVal);
2161 pc += 1;
2162 }
2163 }
2164 assert(Instruction.opLength(bc) == (pc - curPC));
2165 continue;
2166 }
2167
2168 if (bc >= _bytecode_limit)
2169 Utils.log.warning("unrecognized bytescode "+bc
2170 +" "+Instruction.byteName(bc));
2171 assert(bc < _bytecode_limit);
2172 buf[pc++] = (byte) bc;
2173 assert(Instruction.opLength(bc) == (pc - curPC));
2174 continue;
2175 }
2176 }
2177
2178 code.setBytes(realloc(buf, pc));
2179 code.setInstructionMap(insnMap, numInsns);
2180
2181 Instruction ibr = null;
2182 for (int i = 0; i < numLabels; i++) {
2183 int curPC = labels[i];
2184
2185 ibr = Instruction.at(code.bytes, curPC, ibr);
2186 if (ibr instanceof Instruction.Switch) {
2187 Instruction.Switch isw = (Instruction.Switch) ibr;
2188 isw.setDefaultLabel(getLabel(bc_label, code, curPC));
2189 int caseCount = isw.getCaseCount();
2190 for (int j = 0; j < caseCount; j++) {
2191 isw.setCaseLabel(j, getLabel(bc_label, code, curPC));
2192 }
2193 } else {
2194 ibr.setBranchLabel(getLabel(bc_label, code, curPC));
2195 }
2196 }
2197 if (fixupBuf.size() > 0) {
2198 if (verbose > 2)
2199 Utils.log.fine("Fixups in code: "+fixupBuf);
2200 code.addFixups(fixupBuf);
2201 }
2202 }
2203 }
2204 }